package Problemas;
import Busquedas.Estado;


	/**
	Estado (posA,bloqA, posB,bloqB, posC,bloqC)
	bloqA=1 significa que A tiene un bloque encima. =0 no tiene bloque encima.
	1=suelo    2=medio        3=cima
	INICIAL (2,1, 1,1, 3,0) por ejemplo de arriba abajo c,a,b
	FINAL (3,0, 2,1, 1,1) de arriba abajo a,b,c
**/
public class MundoBloques extends Problema{

	private int posA;
	
	private int posB;
	
	private int posC;
	
	private int bloqA;
	
	private int bloqB;
	
	private int bloqC;

    private int[] obje;
	
	
	/**
	 * Constructor de la clase
	 */
	public MundoBloques(){
		int[] paramInicial={2,1, 1,1, 3,0};
		int[] paramObjetivo = {3,0, 2,1, 1,1};
		Estado inicial = new Estado(paramInicial);
		Estado [] objetivo = new Estado[1];
        objetivo[0] = new Estado(paramObjetivo);
		obje=paramObjetivo;
        String [] nombresOperadores={"padre","ponEnMesa","ponBSobreA","ponCSobreA","ponASobreB","ponCSobreB","ponASobreC","ponBSobreC"};
		int [] costeOperadores={1,1,1,1,1,1,1};
		inicializa(inicial,objetivo,7,nombresOperadores,costeOperadores);
	}

	
	/**
	 * asigna los parametros del estado dado.
	 * @param e estado dado.
	 */
	public void asignaParametros(Estado actual){
		posA = actual.getParametro(0);
		bloqA = actual.getParametro(1);
		posB = actual.getParametro(2);	
		bloqB = actual.getParametro(3);
		posC = actual.getParametro(4);
		bloqC = actual.getParametro(5);
	}

	
	/**
	 * 
	 *  Devolver null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado ponEnMesa(Estado actual){
		if ((posA == 3)&&(posB == 2)){
			posA=1;
			bloqB=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}else if ((posA == 3)&&(posC == 2)){
			posA=1;
			bloqC=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}else if ((posA == 2)&&(bloqA == 0)&&(bloqB == 1)){
			posA=1;
			bloqB=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}else if ((posA == 2)&&(bloqA == 0)&&(bloqC == 1)){
			posA=1;
			bloqC=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		//--------------------------------------------------------------
		}else if ((posB == 3)&&(posA == 2)){
			posB=1;
			bloqA=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}else if ((posB == 3)&&(posC == 2)){
			posB=1;
			bloqC=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}else if ((posB == 2)&&(bloqB == 0)&&(bloqA == 1)){
			posB=1;
			bloqA=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}else if ((posB == 2)&&(bloqB == 0)&&(bloqC == 1)){
			posB=1;
			bloqC=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		//--------------------------------------------------------------
		}else if ((posC == 3)&&(posB == 2)){
			posC=1;
			bloqB=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}else if ((posC == 3)&&(posA == 2)){
			posC=1;
			bloqA=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}else if ((posC == 2)&&(bloqC == 0)&&(bloqB == 1)){
			posC=1;
			bloqB=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}else if ((posC == 2)&&(bloqC == 0)&&(bloqA == 1)){
			posC=1;
			bloqA=0;
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}
	 return null;
	}

		
	/**
	 * 
	 *  Devolver� null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado ponBSobreA(Estado actual){
		
		if ((bloqB == 0)&&(bloqA == 0)){
			if (posB==posC+1){ 
				bloqA=1;
				posB=posA+1;
				bloqC=0;
			}
			else{
				bloqA=1;
				posB=posA+1;
			}
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}
		return null;
	}


	/**
	 * 
	 *  Devolver� null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado ponCSobreA(Estado actual){
		
		if ((bloqC == 0)&&(bloqA == 0)){
			if (posC==posB+1){
				bloqA=1;
				posC=posA+1;
				bloqB=0;
			}
			else{
				bloqA=1;
				posC=posA+1;
				//bloqB=0;
			}	
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}
		return null;
	}
	
	
	/**
	 * 
	 *  Devolver� null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado ponASobreB(Estado actual){
		
		if ((bloqA == 0)&&(bloqB == 0)){
			if (posA==posC+1){
				bloqB=1;
				posA=posB+1;
				bloqC=0;
			}
			else{	
				bloqB=1;
				posA=posB+1;
				//bloqC=0;
			}
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}
		return null;
	}
	
	
	
	/**
	 * 
	 *  Devolver� null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado ponCSobreB(Estado actual){
		
		if ((bloqC == 0)&&(bloqB == 0)){
			if (posC==posA+1){
				bloqB=1;
				posC=posB+1;
				bloqA=0;	
			}
			else{	
				bloqB=1;
				posC=posB+1;
				//bloqA=0;
			}
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}
		return null;
	}
	
	
	/**
	 * 
	 *  Devolver� null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado ponASobreC(Estado actual){
		
		if ((bloqA == 0)&&(bloqC == 0)){
			if (posA==posB+1){
				bloqC=1;
				posA=posC+1;
				bloqB=0;
			}
			else{
				bloqC=1;
				posA=posC+1;
				//bloqB=0;
			}
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}
		return null;
	}
	
	
	
	/**
	 * 
	 *  Devolver� null si no se puede aplicar el operador
	 * @param actual estado en el que nos encontramos
	 * @return estado resultante
	 */
	public Estado ponBSobreC(Estado actual){
		
		if ((bloqB == 0)&&(bloqC == 0)){
			if (posB==posA+1){
				bloqC=1;
				posB=posC+1;
				bloqA=0;
			}
			else{
				bloqC=1;
				posB=posC+1;
				//bloqA=0;
			}
			int param[] = {posA,bloqA, posB,bloqB, posC,bloqC};
			return new Estado(param);
		}
		return null;
	}
	
	
	/** Devuelve si es un estado de peligro
	 * @param e estado que comprobamos
	 * @return si es de peligro
	 */
	public boolean peligro(Estado e){
		asignaParametros(e);
		boolean bSobreA, cSobreB, cSobreA;
		bSobreA=((posA<posB)&&(bloqA==1));
		cSobreB=((posB<posC)&&(bloqB==1));
		cSobreA=((posA<posC)&&(bloqA==1));
		return ((bSobreA) || (cSobreB) || (cSobreA));
	}
	
	
	/* (non-Javadoc)
	 * @see Problema#getOperadorInverso(int)
	 */
	public int getOperadorInverso(int op){
		return -1;
	}
	
	
	/* (non-Javadoc)
	 * @see Problema#aplicaOperador(Estado, int)
	 */
	public Estado aplicaOperador(Estado actual,int i){
		asignaParametros(actual);
        Estado siguiente = null;
		switch(i){
		case 0:
			siguiente = ponEnMesa(actual);
			break;
		case 1:
			siguiente = ponBSobreA(actual);
			break;
		case 2:
			siguiente = ponCSobreA(actual);
			break;
		case 3:
			siguiente = ponASobreB(actual);
			break;
		case 4:
			siguiente = ponCSobreB(actual);
		break;
		case 5:
			siguiente = ponASobreC(actual);
			break;
		case 6:
			siguiente = ponBSobreC(actual);
			break;
		}
		if ((siguiente!=null) && (peligro(siguiente))){
			return null;
		}
		return siguiente;
	}

    public int funcionHeuristica(Estado estado){
        //numero de bloques descolocados
        asignaParametros(estado);
        int aux=0;
        int[] ob=getObje();
        if (posA != ob[0]) aux++;
        if (posB != ob[2]) aux++;
        if (posC != ob[4]) aux++;
		return aux;

	}

    
    

    /**
     * @return the obje
     */
    private int[] getObje() {
        return obje;
    }

	
}